import * as _ from 'lodash';
import { Injectable } from '@nestjs/common';
// import moment from 'moment-timezone';
import superagent, { Response } from 'superagent';

import { ERR_MSG } from '../../types/errcode';
import { BusinessException } from '../../types/exception/business.exception';

import { RedisService } from '../../database/redis/redis.service';
import { MongodbService } from '../../database/mongodb/mongodb.service';
import mongoose, { mongo } from 'mongoose';

import { ParamFormat } from '../../class/param/param.class';

// DTO
import { AddDto } from './dto/add.dto';
import { EditDto } from './dto/edit.dto';

// static
import { ROLE } from '../../config/role/index';

@Injectable()
export class SysMenuService {
  constructor(
    private readonly _mongodbService: MongodbService,
    private _redisService: RedisService,
  ) {}

  // 菜单权限初始化
  async initMenu() {
    // 获取静态文件
    const targetObj = ROLE.PERMISSION_INIT;

    // 循环对象每一个key
    for (const key in targetObj) {
      // 存储每一行数据
      // permission 是唯一的
      await this._mongodbService.MenuModel.updateOne(
        { permission: key },
        {
          $set: {
            nodetype: targetObj[key]['nodetype'],
            business: targetObj[key]['business'],
            name: targetObj[key]['name'],
            permission: key,
            parent: targetObj[key]['parent'],
          },
        },

        { upsert: true },
      );
    }

    // 已完成入库
    // 后续需要初始化 角色 用户 等信息
    return {
      msg: true,
    };
  }

  // 同步菜单 超级管理员
  async syncMenuSuper() {
    // 查所有菜单
    const allMenu = await this._mongodbService.MenuModel.find().lean();

    // 更新对象
    const updateObj = {};
    // 中文名数组
    const permissionName = [];
    // 对象数组
    const permission = [];
    //
    const rolePermissionCode = [];

    // 循环 得出一个 permission组成的数组
    for (const item of allMenu) {
      // 中文名
      permissionName.push(item['name']);
      // 对象
      permission.push({
        code: item['permission'],
        label: {
          name: item['name'],
          business: item['business'],
          nodetype: item['nodetype'],
          parent: item['parent'],
        },
      });
      rolePermissionCode.push(item['permission']);
    }

    updateObj['rolePermissionName'] = permissionName;
    updateObj['rolePermission'] = permission;
    updateObj['rolePermissionCode'] = rolePermissionCode;

    // 更新超级管理员
    await this._mongodbService.RoleModel.updateOne({ roleCode: 'admin' }, { $set: updateObj });
  }

  // 增
  async add(req: any, body: AddDto) {
    // 当前人 人员工号
    const { user } = req;
    // 获取参数
    const { nodetype, business, name, permission, description, route, parent } = body;

    // 节点名称 检测
    const checkName = await this._mongodbService.MenuModel.findOne({
      name,
    });
    // 检测名称是否重复
    if (!_.isEmpty(checkName)) {
      // 说明有重复
      throw new BusinessException(ERR_MSG.MENU_NODE_NAME_REPEAT);
    }

    // 权限标识 检测
    const checkPermission = await this._mongodbService.MenuModel.findOne({
      permission,
    });
    // 检测权限是否重复
    if (!_.isEmpty(checkPermission)) {
      // 说明有重复
      throw new BusinessException(ERR_MSG.MENU_NODE_PERMISSION_REPEAT);
    }

    // 如果存在 上级节点  parent
    // 需要检测是否存在 不存在需要报错
    if (parent) {
      const checkParent = await this._mongodbService.MenuModel.findOne({
        permission: parent,
      });
      if (_.isEmpty(checkParent)) {
        // 父级不存在
        // 抛出异常
        throw new BusinessException(ERR_MSG.MENU_NODE_PARENT_NOT_EXIST);
      }
    }

    // 存储
    await this._mongodbService.MenuModel.create({
      nodetype,
      business,
      name,
      permission,
      description,
      route,
      parent,
    });

    // 更新超级管理员
    this.syncMenuSuper();

    return {
      msg: true,
    };
  }

  // 删
  async del(req: any) {
    // 当前人 人员工号
    const { user } = req;
    // 获取参数
    const { id } = req.query;

    // 删除前要检查 无子节点

    //  检测是否存在
    const menuInfo = await this._mongodbService.MenuModel.findById(id);
    if (_.isEmpty(menuInfo)) throw new BusinessException(ERR_MSG.MENU_NOT_EXIST);

    // 检查是否有子集
    const menuList = await this._mongodbService.MenuModel.find({
      parentId: id,
    });
    if (!_.isEmpty(menuList)) throw new BusinessException(ERR_MSG.MENU_HAS_CHILDREN);

    // 删除
    await this._mongodbService.MenuModel.findByIdAndDelete(id);

    // 更新超级管理员
    this.syncMenuSuper();

    return {
      msg: true,
    };
  }

  // 改
  async edit(req: any, body: EditDto) {
    // 当前人 人员工号
    const { user } = req;

    // 获取参数
    const { id, nodetype, business, name, permission, description, route, parent } = body;

    // 节点名称 检测
    const checkName = await this._mongodbService.MenuModel.findOne({
      name,
    });

    // 检测id是否存在
    const checkId = await this._mongodbService.MenuModel.findById(id);

    if (_.isEmpty(checkId)) {
      throw new BusinessException(ERR_MSG.MENU_NOT_EXIST);
    }

    // 检测名称是否重复
    // 如果名称变更了
    if (name !== checkId.name) {
      if (!_.isEmpty(checkName)) {
        throw new BusinessException(ERR_MSG.MENU_NODE_NAME_REPEAT);
      }
    }

    // 权限标识 检测
    // 如果权限标识变更了
    if (permission !== checkId.permission) {
      const checkPermission = await this._mongodbService.MenuModel.findOne({
        permission,
      });
      // 检测权限是否重复
      if (!_.isEmpty(checkPermission)) {
        throw new BusinessException(ERR_MSG.MENU_NODE_PERMISSION_REPEAT);
      }
    }

    // 如果存在 上级节点  parent
    // 需要检测是否存在 不存在需要报错
    if (parent) {
      const checkParent = await this._mongodbService.MenuModel.findOne({
        permission: parent,
      });
      if (_.isEmpty(checkParent)) {
        throw new BusinessException(ERR_MSG.MENU_NODE_PARENT_NOT_EXIST);
      }
    }

    // 存储
    await this._mongodbService.MenuModel.updateOne(
      {
        _id: new mongoose.Types.ObjectId(id),
      },
      {
        $set: {
          nodetype,
          business,
          name,
          permission,
          description,
          route,
          parent,
        },
      },
    );

    // 更新超级管理员
    this.syncMenuSuper();

    return {
      msg: true,
    };
  }

  // 递归获取子级 组成 children
  async getChildren(list, obj) {
    // 找到本层级的子集
    const children = list.filter(item => item.parent === obj.permission);

    // 接着找各自子集
    for (const item of children) {
      const child = await this.getChildren(list, item);
      item.children = child;
    }
    return children;
  }
  // 树状结构
  async findTree(req: any) {
    // 获取所有菜单
    const all = await this._mongodbService.MenuModel.find().lean();
    // 组成树状结构
    // 找到头节点
    const rootPC = await this._mongodbService.MenuModel.findOne({
      permission: 'pc',
    }).lean();
    if (_.isEmpty(rootPC)) {
      throw new BusinessException(ERR_MSG.MENU_MISSING_ROOT);
    }
    const rootAPP = await this._mongodbService.MenuModel.findOne({
      permission: 'app',
    }).lean();
    if (_.isEmpty(rootAPP)) {
      throw new BusinessException(ERR_MSG.MENU_MISSING_ROOT);
    }

    const treePC = await this.getChildren(all, rootPC);
    rootPC['children'] = treePC;

    const treeAPP = await this.getChildren(all, rootAPP);
    rootAPP['children'] = treeAPP;
    return {
      rootPC,
      rootAPP,
    };
  }
}
